package chat

import "github.com/docker/cagent/pkg/tools"

type MessageRole string

const (
	MessageRoleSystem    MessageRole = "system"
	MessageRoleUser      MessageRole = "user"
	MessageRoleAssistant MessageRole = "assistant"
	MessageRoleTool      MessageRole = "tool"
)

type MessagePartType string

const (
	MessagePartTypeText     MessagePartType = "text"
	MessagePartTypeImageURL MessagePartType = "image_url"
)

type ImageURLDetail string

const (
	ImageURLDetailHigh ImageURLDetail = "high"
	ImageURLDetailLow  ImageURLDetail = "low"
	ImageURLDetailAuto ImageURLDetail = "auto"
)

type MessageImageURL struct {
	URL    string         `json:"url,omitempty"`
	Detail ImageURLDetail `json:"detail,omitempty"`
}

type Message struct {
	Role         MessageRole   `json:"role"`
	Content      string        `json:"content"`
	Refusal      string        `json:"refusal,omitempty"`
	MultiContent []MessagePart `json:"multi_content,omitempty"`

	// This property isn't in the official documentation, but it's in
	// the documentation for the official library for python:
	// - https://github.com/openai/openai-python/blob/main/chatml.md
	// - https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb
	Name string `json:"name,omitempty"`

	// This property is used for the "reasoning" feature supported by deepseek-reasoner
	// which is not in the official documentation.
	// the doc from deepseek:
	// - https://api-docs.deepseek.com/api/create-chat-completion#responses
	ReasoningContent string `json:"reasoning_content,omitempty"`

	// ThinkingSignature is used for Anthropic's extended thinking feature
	ThinkingSignature string `json:"thinking_signature,omitempty"`

	ThoughtSignature []byte `json:"thought_signature,omitempty"`

	FunctionCall *tools.FunctionCall `json:"function_call,omitempty"`

	// For Role=assistant prompts this may be set to the tool calls generated by the model, such as function calls.
	ToolCalls []tools.ToolCall `json:"tool_calls,omitempty"`

	// For Role=tool prompts this should be set to the ID given in the assistant's prior request to call a tool.
	ToolCallID string `json:"tool_call_id,omitempty"`

	CreatedAt string `json:"created_at,omitempty"`
}

type MessagePart struct {
	Type     MessagePartType  `json:"type,omitempty"`
	Text     string           `json:"text,omitempty"`
	ImageURL *MessageImageURL `json:"image_url,omitempty"`
}

// FinishReason represents the reason why the model finished generating a response
type FinishReason string

const (
	// FinishReasonStop means the model reached a natural stopping point or the max tokens
	FinishReasonStop FinishReason = "stop"
	// FinishReasonLength means the model reached the token limit
	FinishReasonLength FinishReason = "length"
	// FinishReasonToolCalls means the model called a tool
	FinishReasonToolCalls FinishReason = "tool_calls"
	// FinishReasonFunctionCall is used when the model calls a function (legacy)
	FinishReasonFunctionCall FinishReason = "function_call"
	// FinishReasonContentFilter means the content was filtered
	FinishReasonContentFilter FinishReason = "content_filter"
	// FinishReasonNull means no finish reason was provided
	FinishReasonNull FinishReason = "null"
)

// MessageDelta represents a delta/chunk in a streaming response
type MessageDelta struct {
	Role              string              `json:"role,omitempty"`
	Content           string              `json:"content,omitempty"`
	ReasoningContent  string              `json:"reasoning_content,omitempty"`
	ThinkingSignature string              `json:"thinking_signature,omitempty"`
	ThoughtSignature  []byte              `json:"thought_signature,omitempty"`
	FunctionCall      *tools.FunctionCall `json:"function_call,omitempty"`
	ToolCalls         []tools.ToolCall    `json:"tool_calls,omitempty"`
}

// MessageStreamChoice represents a choice in a streaming response
type MessageStreamChoice struct {
	Index        int          `json:"index"`
	Delta        MessageDelta `json:"delta"`
	FinishReason FinishReason `json:"finish_reason,omitempty"`
}

// MessageStreamResponse represents a streaming response from the model
type MessageStreamResponse struct {
	ID      string                `json:"id"`
	Object  string                `json:"object"`
	Created int64                 `json:"created"`
	Model   string                `json:"model"`
	Choices []MessageStreamChoice `json:"choices"`
	Usage   *Usage                `json:"usage,omitempty"`
}

type Usage struct {
	InputTokens        int `json:"input_tokens"`
	OutputTokens       int `json:"output_tokens"`
	CachedInputTokens  int `json:"cached_input_tokens"`
	CachedOutputTokens int `json:"cached_output_tokens"`
	ReasoningTokens    int `json:"reasoning_tokens,omitempty"`
}

// MessageStream interface represents a stream of chat completions
type MessageStream interface {
	// Recv gets the next completion chunk
	Recv() (MessageStreamResponse, error)
	// Close closes the stream
	Close()
}
